// @HEADER
//*********************************************************************//
//  SiYuan: A numerical PDE solver                                     //
//  Copyright (2022) YUAN Xi                                           //
//  This Software is released under the BSD 2-Clause license detailed  //
//  in the file "LICENSE" in the top-level SiYuan directory            //
//*********************************************************************//
// @HEADER

#ifndef XYFEM_MATERIALBASE_h_
#define XYFEM_MATERIALBASE_h_

#include <unordered_map>
#include <array>
#include <memory>

#include "valfunctor.hpp"

namespace SiYuan
{
	enum StainType {Inifinite=0, GreenLagrangian, Log};
	
   /* Material can be constructed by elastic, plastic, visco etc*/
   class Material
   {
      typedef std::valarray<double>   evalT;
      typedef std::unordered_map<std::string, std::shared_ptr<XYZLib::variable<double>> > dataT;
      typedef dataT::const_iterator iterT;

      public:
		   dataT  items;

      public:
         Material() {};
         Material(const Teuchos::ParameterList& params);
         // construct Material with given name
         Material(const std::string& name, const Teuchos::ParameterList& params);

         template <typename... Args>
         evalT fetch(const std::string& name, const Args... args) const {
            if( items.find(name) != items.end() ) {
             //  auto a = materials.at(name);
               return items.at(name)->fetch(args...);
            } else {
               return evalT();
            }   
         }

         void print(std::ostream& os = std::cout) const;
         iterT begin() const {return items.begin();}
         iterT end() const {return items.end();}

         // number of parameters of property with name given
         unsigned int size(const std::string& name) const {
            if( items.find(name) != items.end() ) {
               return items.at(name)->size();
            } else {
               return 0;
            }   
         }
   };

   typedef std::unordered_map<std::string, std::shared_ptr<Material> >  CMaterials;

   void buildMaterials(CMaterials& materials, const Teuchos::ParameterList& p);
   void printMaterials(CMaterials& materials, std::ostream& os = std::cout);

  // struct MaterialObjContainer
  // {
 //     std::vector<PHX::MDField<const ScalarT, panzer::Cell, panzer::IP, panzer::Dim>> matlProps;
  // }

} // End of namespace

#endif
